/*
 * Copyright (c) 2022. China Mobile (SuZhou) Software Technology Co.,Ltd. All rights reserved.
 * Lakehouse is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */

package com.chinamobile.cmss.lakehouse.common.utils;

import java.time.Duration;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Supplier;

public class WaitUtil {

    public static boolean poll(Duration interval, Duration timeout, Supplier<Boolean> condition) {
        return poll(interval, interval, timeout, condition);
    }

    public static boolean poll(
        Duration initialDelay, Duration interval, Duration timeout, Supplier<Boolean> condition) {
        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        AtomicBoolean result = new AtomicBoolean(false);
        long dueDate = System.currentTimeMillis() + timeout.toMillis();
        ScheduledFuture<?> future =
            executorService.scheduleAtFixedRate(
                () -> {
                    try {
                        result.set(condition.get());
                    } catch (Exception e) {
                        result.set(false);
                    }
                },
                initialDelay.toMillis(),
                interval.toMillis(),
                TimeUnit.MILLISECONDS);
        try {
            while (System.currentTimeMillis() < dueDate) {
                if (result.get()) {
                    future.cancel(true);
                    return true;
                }
            }
        } catch (Exception e) {
            return result.get();
        }
        future.cancel(true);
        return result.get();
    }
}
